package com.zhu.classfile.constant;

import com.zhu.classfile.constant.base.ConstantClassInfo;
import com.zhu.classfile.constant.base.ConstantUtf8Info;
import com.zhu.classfile.constant.factory.ConstantInfoFactory;

import java.nio.ByteBuffer;

/**
 * 映射二进制常量池
 * JVM 的“基本单位”是 32 位
 * 在 JVM 的设计中，
 * 无论是：
 * 操作数栈（Operand Stack）
 * 局部变量表（Local Variable Table）
 * 还是常量池（Constant Pool）的索引管理
 * 它们的基本存储单元是 32 位（4 字节），称为一个 slot。
 */
public class ConstantPool {
    // 索引 0 留空
    private final ConstantInfo[] constants;

    private ConstantPool(ConstantInfo[] constants) {
        this.constants = constants;
    }

    // 静态工厂：既创建池，也解析常量
    public static ConstantPool readConstantPool(ByteBuffer reader,int constantPoolCount) {
        ConstantInfo[] constants = new ConstantInfo[constantPoolCount];
        // 先创建池对象（此时为空）
        ConstantPool cp = new ConstantPool(constants);

        for (int i = 1; i < constantPoolCount; i++) {
            if (reader.remaining() == 0) {
                throw new RuntimeException("Class file truncated");
            }
            //安全地读取一个无符号 uint8 类型的 tag
            int tag = Byte.toUnsignedInt(reader.get());
            ConstantInfo ci = readConstantInfo(reader, cp, tag);
            constants[i] = ci;
            System.out.println("现在解析的常量的数组下标是:"+i);
            // 占两个 slot 的类型
            if (tag == ConstantTag.CONSTANT_Long.getTagVal() || tag == ConstantTag.CONSTANT_Double.getTagVal()) {
                //而 long 和 double 是 64 位，必须跨越两个 32 位 slot 才能完整表示。
                i++;
            }
        }

        return cp;
    }

    private static ConstantInfo readConstantInfo(ByteBuffer reader, ConstantPool cp, int tag) {
        ConstantInfo ci = ConstantInfoFactory.newConstantInfo(tag, cp);
        ci.readInfo(reader);
        return ci;
    }

    /**
     * 根据索引获取常量（索引从 1 开始）
     */
    public ConstantInfo get(int index) {
        if (index == 0 || index >= constants.length) {
            throw new RuntimeException("Invalid constant pool index: " + index);
        }
        return constants[index];
    }


    public String getClassName(int index){
        ConstantInfo constantInfo = get(index);
        if (!(constantInfo instanceof ConstantClassInfo)){
            throw new RuntimeException("Constant pool entry at index " + index +
                    " is not a CONSTANT_Class_info");
        }
       return ((ConstantClassInfo) constantInfo).getClassName();

    }

    public int size() {
        return constants.length;
    }

    /**
     * 根据索引获取 CONSTANT_Utf8_info 的字符串值
     * 用于 SourceFile、Signature、Class 等属性
     *
     * @param index 常量池索引（从 1 开始）
     * @return 对应的字符串
     * @throws RuntimeException 如果索引无效或类型不是 CONSTANT_Utf8_info
     */
    public String getUtf8(int index) {
        ConstantInfo constantInfo = get(index);
        if (!(constantInfo instanceof ConstantUtf8Info)) {
            throw new RuntimeException("Constant pool entry at index " + index +
                    " is not a CONSTANT_Utf8_info");
        }
        return ((ConstantUtf8Info) constantInfo).getValue();
    }
    public int getSize(){
        if (constants==null){
            return 0;
        }
        return constants.length;
    }
}
